package com.cloud.util.base;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.hibernate.type.StandardBasicTypes;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate4.support.HibernateDaoSupport;



/**
 * 通用泛型DAO 接口Hibernate适配器 本系统中的所有持久层访问类都继承此适配器类
 * 
 * @version 1.0
 * @date 2012-09-01
 * @author DWZ框架组
 */
public class BaseHibernateDao<T, ID extends Serializable> extends
		HibernateDaoSupport{

	/* 持久操作实体Bean对象类别 */
	private Class<T> persistentClass;

	/**
	 * 通过构造器来注入泛型对应的类
	 */
	public BaseHibernateDao(Class<T> clazz) {
		this.persistentClass = clazz;
	}

	/**
	 * 自动识别对应的类
	 */
	@SuppressWarnings("unchecked")
	public BaseHibernateDao() {

		Class c = getClass();
		java.lang.reflect.Type t = c.getGenericSuperclass();
		if (t instanceof java.lang.reflect.ParameterizedType) {
			java.lang.reflect.ParameterizedType paramterizedType = (java.lang.reflect.ParameterizedType) t;
			java.lang.reflect.Type[] p = paramterizedType
					.getActualTypeArguments();
			this.persistentClass = (Class<T>) p[0];
		}

	}
	
	@Autowired
	public void setSuperSessionFactory(SessionFactory sessionFactory){
	    super.setSessionFactory(sessionFactory);
	}

	protected Class<T> getPersistentClass() {

		return persistentClass;

	}

	/**
	 * 根据ID及指定的实体类别对象，加载实体域对象
	 */
	public T findById(Class<T> c, ID id) {

		try {
			T entity;
			entity = (T) getHibernateTemplate().get(c, id);
			return entity;
		} catch (IllegalArgumentException ie) {
			return null;
		}

	}

	/**
	 * 根据ID,加载实现类指定的泛型实体对象
	 */
	public T findById(ID id) {

		try {
			T entity = (T) getHibernateTemplate().get(getPersistentClass(), id);
			return entity;
		} catch (IllegalArgumentException ie) {
			return null;
		}

	}
	/**
	 * 由于在mysql中ID为int类型 自增  且没有序列化  故另增一函数
	 * 根据ID,加载实现类指定的泛型实体对象
	 */
	public T findById(int id) {

		try {
			T entity = (T) getHibernateTemplate().get(getPersistentClass(), id);
			return entity;
		} catch (IllegalArgumentException ie) {
			return null;
		}

	}

	/**
	 * 根据ID,加载实现类指定的泛型实体代理对象
	 */
	public T loadById(ID id) {

		T entity = (T) getHibernateTemplate().load(getPersistentClass(), id);

		return entity;

	}

	/**
	 * 根据及指定的实体域类别对象,加载实体域代理对象
	 */
	@SuppressWarnings("unchecked")
	public T loadById(Class c, ID id) {

		T entity = (T) getHibernateTemplate().load(c, id);

		return entity;

	}

	/**
	 * 加载实现类指定的泛型实体对象
	 */
	public List<T> loadAll() {
		return getHibernateTemplate().loadAll(getPersistentClass());
	}

	/**
	 * 保存实现类指定的泛型实体对象
	 */
	public T saveEntity(T entity) {

		getHibernateTemplate().save(entity);
		this.flush();

		return entity;

	}
	
	/**
	 * 保存实现类指定的List泛型实体对象
	 */
	public List<T> saveEntities(List<T> entityList){
		for(int i=0; i<entityList.size(); i++){
			
			T tempEntity=entityList.get(i);
			getHibernateTemplate().save(tempEntity);
			
			if(i!=0 && i%20==0){
				this.flush();
				this.clear();
			}
		}
		
		this.flush();
		return entityList;
	}
	
	/**
	 * 更新实现类指定的泛型实体对象
	 */
	public void updateEntity(T entity) {

		getHibernateTemplate().saveOrUpdate(entity);

		this.flush();

	}
	
	/**
	 * 保存实现类指定的List泛型实体对象
	 */
	public List<T> updateEntities(List<T> entityList){
		for(int i=0; i<entityList.size(); i++){
			
			T tempEntity=entityList.get(i);
			getHibernateTemplate().saveOrUpdate(tempEntity);
			
			if(i!=0 && i%20==0){
				this.flush();
				this.clear();
			}
		}
		
		this.flush();
		return entityList;
	}

	/**
	 * 根据实体,删除实现类指定的泛型实体对象
	 */
	public void deleteEntity(T entity) {

		getHibernateTemplate().delete(entity);
		this.flush();

	}

	/**
	 * 根据实体ID,删除实现类指定的泛型实体对象
	 */
	public void deleteEntityById(ID id) {

		this.deleteEntity(this.loadById(id));
		this.flush();

	}

	/**
	 * 删除实现类指定的泛型所有实体对象
	 */
	public void deleteAll(Collection<T> entities) {

		getHibernateTemplate().deleteAll(entities);
		this.flush();

	}
	
	/**
	 * 执行原生SQL
	 * @param sql
	 */
	public void executeQuery(String sql){
		Session session = currentSession();
		session.createSQLQuery(sql).executeUpdate();
	}

	/**
	 * 通过合并的方式更新对象
	 */
	public void merge(T entity) {

		getHibernateTemplate().merge(entity);
		this.flush();

	}
	
	/**
	 * 使用HQL语句进行对象的查询 
	 * 
	 * @param hsql
	 *            查询语句
	 * @return 符合条件的对象
	 */
	@SuppressWarnings("unchecked")
	public T getEntity(String hsql) {

		List list = getHibernateTemplate().find(hsql);
		if (null == list || 0 == list.size()) {
			return null;
		}
		return (T) list.get(0);

	}

	/**
	 * 使用HQL语句进行对象的查询 
	 * 
	 * @param hsql
	 *            查询语句
	 * @return 符合条件的对象
	 */
	@SuppressWarnings("unchecked")
	public T getEntity(String hsql, Object... values) {

		List list = getHibernateTemplate().find(hsql, values);
		if (null == list || 0 == list.size()) {
			return null;
		}
		return (T) list.get(0);

	}
	
	/**
	 * 使用HQL语句进行对象的查询_只查一条
	 * @param hsql
	 * @return
	 */
	public T getEntityOne(String hsql){
		
		List list = null;
		Session session = currentSession();

		list = session.createQuery(hsql).setFirstResult(0).setMaxResults(1).list();
		if (null == list || list.isEmpty()) {
			return null;
		}
		
		return (T) list.get(0);
	}
	
	/**
	 * 使用HQL语句进行对象的查询_只查一条
	 * @param hsql
	 * @return
	 */
//	public TableOneMonthReport getOneMonthReport(String hsql){
//		
//		List list = null;
//		Session session = currentSession();
//
//		list = session.createQuery(hsql).setFirstResult(0).setMaxResults(1).list();
//		if (null == list || list.isEmpty()) {
//			return null;
//		}
//		
//		return (TableOneMonthReport) list.get(0);
//	}
	/**
	 * 使用HQL语句进行查询
	 * 
	 * @param hsql
	 *            查询语句
	 * @return 符合条件的对象集集合
	 */
	@SuppressWarnings("unchecked")
	public List<T> getEntities(String hsql) {

		return (List<T>) getHibernateTemplate().find(hsql);

	}
	
	/**
	 * 使用HQL语句进行查询
	 * 
	 * @param hsql
	 *            查询语句
	 * @return 符合条件的对象集集合
	 */
	@SuppressWarnings("unchecked")
	public List<T> getEntities(String hsql, Object... values) {

		return (List<T>) getHibernateTemplate().find(hsql, values);

	}
	
	/**
	 * 使用HQL语句进行查询
	 * 
	 * @param hsql
	 *            查询语句
	 * @return 符合条件的对象集集合
	 */
	@SuppressWarnings("unchecked")
	public List<T> getEntitiesPage(String hsql, int page, int pageSize) {

		List list = null;
		Session session = currentSession();

		list = session.createQuery(hsql).setFirstResult(
				(page - 1) * pageSize).setMaxResults(pageSize).list();
		if (null == list) {
			list = new ArrayList();
		}
		
		return list;
	}
	
	/**
	 * 原生sql分页查询
	 * @param sql
	 * @param page
	 * @param pageSize
	 * @return
	 */
	public List getSQLQuery(String sql, int page, int pageSize) {
		List list = null;
		Session session = currentSession();
		
		list = session.createSQLQuery(sql)
				.setFirstResult((page - 1) * pageSize)
				.setMaxResults(pageSize).list();
		
		return list;
	}
	
	/**
	 * 原生sql查询
	 * @param sql
	 * @return
	 */
	public List getSQLQuery(String sql) {
		List list = null;
		Session session = currentSession();
		
		list = session.createSQLQuery(sql).list();
		
		return list;
	}
	
	/**
	 * 原生sql查询
	 * @param sql
	 * @return
	 */
	public List getSQLQuery(String sql, Map<String, org.hibernate.type.Type> type) {
		List list = null;
		Session session = currentSession();
		
		SQLQuery query = session.createSQLQuery(sql);
		if(type != null){
			for (Map.Entry<String, org.hibernate.type.Type> entry : type.entrySet()) {
				query.addScalar(entry.getKey(), entry.getValue());
			}
		}
		
		list = query.list();
		
		return list;
	}
	
	/**
	 * 原生sql查询，并转换成对象
	 * @param sql
	 * @return
	 */
	public List getSQLQuery(String sql, Class entityClass) {
		List list = null;
		Session session = currentSession();
		
		list = session.createSQLQuery(sql).addEntity(entityClass).list();
		
		return list;
	}
	
	/**
	 * 原生sql查询，只查一条
	 * @param sql
	 * @return
	 */
	public Object getSQLQueryOne(String sql) {
		List list = null;
		Session session = currentSession();
		
		list = session.createSQLQuery(sql).setFirstResult(0)
				.setMaxResults(1).list();
		
		if (null == list || 0 == list.size()) {
			return null;
		}
		
		return list.get(0);
	}

	/**
	 * 使用命名的HQL语句查询数据
	 * 
	 * @param queryName
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<T> findByNamedQuery(String queryName) {

		List<T> list = null;
		Session session = null;

		session = currentSession();
		list = session.getNamedQuery(queryName).list();

		return list;

	}

	/**
	 * 使用带参数的命名HSQL语句查询数据
	 * 
	 * @param queryName
	 * @param values
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<T> findByNamedQuery(String queryName, Object[] values) {

		List<T> list = null;
		Session session = null;

		session = currentSession();
		Query query = session.getNamedQuery(queryName);
		if (values == null) {
		} else {
			for (int i = 0; i < values.length; i++) {
				query.setParameter(i, values[i]);
			}
		}
		list = query.list();

		return list;

	}

	/**
	 * 使用带命名参数的命名HSQL语句 查询数据
	 * 
	 * @param queryName
	 * @param paramNames
	 * @param values
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<T> findByNamedQuery(String queryName, String[] paramNames,
			Object[] values) {

		List<T> list = null;
		Session session = null;

		session = currentSession();
		Query query = session.getNamedQuery(queryName);
		for (int i = 0; i < paramNames.length; i++) {
			query.setParameter(paramNames[i], values[i]);
		}
		list = query.list();

		return list;

	}

	/**
	 * 使用HQL语句查询数据 ，返回Iterator
	 * 
	 * @param queryString
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public Iterator<T> iterate(String hql) {

		Session session = null;
		Iterator<T> list = null;

		session = currentSession();
		list = session.createQuery(hql).iterate();

		return list;

	}

	/**
	 * 使用带参数HSQL语句查询数据，返回Iterator
	 * 
	 * @param queryString
	 * @param values
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public Iterator<T> iterate(String hql, Object[] values) {

		Session session = null;
		Iterator<T> list = null;

		session = currentSession();
		Query query = session.createQuery(hql);
		for (int i = 0; i < values.length; i++) {
			query.setParameter(i, values[i]);
		}
		list = query.iterate();

		return list;

	}

	/**
	 * 强制立即更新缓冲数据到数据库（否则仅在事务提交时才更新）
	 */
	public void flush() {

		getHibernateTemplate().flush();

	}

	/**
	 * 清空缓存 void
	 */
	public void clear() {

		getHibernateTemplate().clear();

	}

	/**
	 * 无分页查询
	 * 
	 * @param criteria
	 * @return 根对象的列表。
	 */
	@SuppressWarnings("unchecked")
	public List<T> findByCriteria(DetachedCriteria criteria) {

		List results = new ArrayList();
		criteria.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
		Iterator<T> it = (Iterator<T>) getHibernateTemplate().findByCriteria(criteria)
				.iterator();
		while (it.hasNext()) {
			Map map = (Map) it.next();
			results.add(map.get(Criteria.ROOT_ALIAS));
		}

		return results;

	}

	/**
	 * 按属性查找唯一对象.
	 */
	@SuppressWarnings("unchecked")
	public T findUniqueByProperty(String propertyName, Object value) {

		return (T) createCriteria(Restrictions.eq(propertyName, value))
				.uniqueResult();

	}

	/**
	 * 根据Criterion条件创建Criteria,后续可进行更多处理,辅助函数.
	 */
	public Criteria createCriteria(Criterion... criterions) {

		Session session = null;
		Criteria criteria = null;

		session = currentSession();
		criteria = session.createCriteria(persistentClass);
		for (Criterion c : criterions) {
			criteria.add(c);
		}

		return criteria;

	}

	/**
	 * 根据字段名查询
	 * 
	 * @param propertyName
	 * @param value
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<T> findByProperty(String propertyName, Object value) {

		String queryString = "from " + this.getPersistentClass().getName()
				+ " as model where model." + propertyName + "= ?";

		return (List<T>) getHibernateTemplate().find(queryString, value);

	}

	public int updateByNamedQuery(String queryName, Object[] values) {

		int cnt = 0;
		Session session = null;

		session = currentSession();
		Query query = session.getNamedQuery(queryName);
		for (int i = 0; i < values.length; i++) {
			query.setParameter(i, values[i]);
		}
		cnt = query.executeUpdate();

		return cnt;

	}

	/* 统计信息 */
	public int count(String hbSql) {

		Session session = currentSession();
		Long count = new Long(0);

		Object temp = session.createQuery(hbSql).uniqueResult();
		count = (Long) temp;
		
		return count.intValue();
	}
	

	/* 信息求和 */
	public int sun(String hbSql) {

		Session session = currentSession();
		Long count = new Long(0);

		Object temp = session.createQuery(hbSql).uniqueResult();
		if(null==temp){
			count=0L;
		}else{
			 count = (Long) temp;
		}
		
		return count.intValue();
	}
	
	/* 信息求和 */
	public Double sumDouble(String hbSql) {

		Session session = currentSession();
		Double count = new Double(0);

		Object temp = session.createQuery(hbSql).uniqueResult();
		if(null==temp){
			count=0D;
		}else{
			 count = (Double) temp;
		}
		
		return count.doubleValue();
	}
	
}
